//
//  Alamofire+Extension.swift
//  zhengwutong
//
//  Created by wangshuguan on 16/8/22.
//  Copyright © 2016年 wangshuguan. All rights reserved.
//

import UIKit
import Alamofire
import CoreTelephony
import SwiftyJSON
public let debugApi = true
public let RD = Session.default
public enum ZWTServiceCode:Int {
    case normal             = 200         //正常
    case unknown            = 99999     //未知错误
    case outTime            = -1        //用户失效
    case parameterError     = -2        //参数有误
    var description:String {
        get{
            switch self {
            case .normal:
                return "正常"
            case .outTime:
                return "用户失效"
            default:
                return "未知错误"
            }
        }
    }
}
extension NSError{
    func msg() -> String {
        var str = ""
        for (key,value) in self.userInfo {
            if ("\(key)".lowercased().contains("description") && !"\(value)".isEmpty) || ("\(key)".lowercased().contains("reason") && !"\(value)".isEmpty) {
                str.append("\(value)")
            }
        }
        return str
    }
}
extension DataResponse{
    var message:String?{
        get{
            switch self.result {
            case .success:
                return JSON(self.value ?? [:])["message"].stringValue
            case .failure:
                if let e = self.error as? AFError{
                    if e.isResponseSerializationError{
                        return "数据加载失败"
                    }else if e.isSessionTaskError{
                        return "网络不可用，请您稍后重试"
                    }
                }
                return ((self.error as? AFError)?.underlyingError as NSError?)?.msg()
            }
        }
    }
}
extension URLRequest{
    func request(with para:Parameters)->URLRequest{
        var urlComponent = URLComponents(string: (self.url?.absoluteString)!)!
        let queryItems = para.map{ URLQueryItem(name: $0.key, value: "\($0.value)") }
        urlComponent.queryItems = queryItems
        return URLRequest(url: urlComponent.url!)
    }
}
extension String{
    func para(_ para:Parameters)->String{
        return URLRequest(url: URL(string:self)!).request(with: para).url?.absoluteString ?? self
    }
}
/// 实际上是替换Alamofire的原生request方法的
extension Session{
    struct RequestConvertible1: URLRequestConvertible {
        let url: URLConvertible
        let method: HTTPMethod
        let parameters: Parameters?
        let encoding: ParameterEncoding
        let headers: HTTPHeaders?

        func asURLRequest() throws -> URLRequest {
            var request = try URLRequest(url: url, method: method, headers: headers)
            request.timeoutInterval = 30
            return try encoding.encode(request, with: parameters)
        }
    }
    open func requestZWT(_ convertible: URLConvertible,
    method: HTTPMethod = .get,
    parameters: Parameters? = nil,
    encoding: ParameterEncoding = URLEncoding.default,
                      headers: HTTPHeaders? = nil,
                      interceptor: RequestInterceptor? = nil,
                      name: String = "") -> DataRequest {
        
        
        #if !DEBUG
        if Config.systemSetting.isProxy {
            return request("proxy".withHost)
        }
        #endif
        
        let h:[String : String] = (headers?.dictionary ?? DataRequest.defaultHTTPHeaders.dictionary)+["pageName":name]
        let convertible = RequestConvertible1(url: convertible,
        method: method,
        parameters: parameters,
        encoding: encoding,
                                             headers: HTTPHeaders(h))

        return request(convertible, interceptor: interceptor)
    }
}
extension DataRequest {
    public static let defaultHTTPHeaders: HTTPHeaders = {
        var header:HTTPHeaders = HTTPHeaders.default
        header["version_code"] = Config.App.version
        header["source_type"] = Config.supportKey.channel
        return header
    }()
    @discardableResult
    public func responseZWTJSON(
        showError:Bool = true,
        queue: DispatchQueue = .main,
        otherInfo:[String:Any] = [:],
        options: JSONSerialization.ReadingOptions = .allowFragments,
        completionHandler: @escaping (AFDataResponse<Any>,ZWTServiceCode,Bool) -> Void)
        -> Self
    {
        var _showError = false
        let myCompletionHandler: (AFDataResponse<Any>) -> Void = {response in
            guard !(response.request?.url?.lastPathComponent.contains("proxy") ?? false) else {
                return
            }
            var myResponse = response
            var errorString:String?
            var code:ZWTServiceCode = .unknown
            switch myResponse.result{
            case .success:
                let json = JSON(myResponse.value ?? [:])
                if let t = ZWTServiceCode(rawValue: json["code"].intValue) {
                    code = t
                }
                if json["result"]["userquit"].boolValue{
                    code = .outTime
                }
                if !json["success"].boolValue {
                    let errorMsg = json["message"].stringValue
                    let errorMsg2 = json["msg"].stringValue
                    if errorMsg.isNotEmpty {
                        errorString = errorMsg
                    }
                    if errorMsg2.isNotEmpty {
                        errorString = errorMsg2
                    }
                    if (errorString ?? "").isEmpty {
                        errorString = "当前网络不稳定，请重试"
                    }
                    _showError = showError
                }else{
                    if json["isMessage"].boolValue{
                        _showError = true
                    }
                }
                if errorString != nil {
                    let error: NSError = NSError(domain: Config.host.hostname, code: code.rawValue, userInfo: [NSLocalizedFailureReasonErrorKey: errorString ?? ""])
                    let afError:AFError = AFError.responseValidationFailed(reason: AFError.ResponseValidationFailureReason.customValidationFailed(error: error))
                    let testResponse: AFDataResponse<Any> = DataResponse(request: response.request, response: response.response, data: response.data, metrics: response.metrics, serializationDuration: response.serializationDuration, result: .failure(afError))
                    myResponse = testResponse
                }
            case .failure:
                let testResponse: AFDataResponse<Any> = {
                                        return DataResponse(request: response.request, response: response.response, data: response.data, metrics: .none, serializationDuration: 0, result: .failure(response.error ?? AFError.createURLRequestFailed(error: NSError(domain: Config.host.hostname, code: -1, userInfo: nil))))
                }()
                myResponse = testResponse
            }
            
            
            //****************** debug things *************************///
            
            switch myResponse.result {
            case .failure:
                #if DEBUG
                ZWTPrint("error description:\(myResponse.message ?? "")")
                func printErrorString(str:String) {
                    let errorString = str.removingPercentEncoding ?? str
                    if errorString.hasPrefix("[")||errorString.hasPrefix("{"), let jsonStr = errorString.toJsonObject(){
                        ZWTPrint(jsonStr)
                    }else{
                        ZWTPrint(errorString)
                    }
                }
                ZWTPrint(myResponse.request ?? "")
                if myResponse.request?.httpBody != nil{
                    if let data = myResponse.request?.httpBody{
                        printErrorString(str: String(data: data, encoding: String.Encoding.utf8) ?? "")
                    }
                }
                if let mydata = myResponse.data {
                    if let str = String(data: mydata, encoding: String.Encoding.utf8){
                        printErrorString(str: str)
                    }else{
                        if let str = String(data: mydata, encoding: String.Encoding.utf8){
                            printErrorString(str:  str)
                        }else{
                            if let str = String(data: mydata, encoding: String.Encoding.utf8){
                                printErrorString(str: str)
                            }
                        }
                    }
                }
                #endif
            default:
                #if DEBUG
                if debugApi{
                    func printErrorString(str:String) {
                        let errorString = str.removingPercentEncoding ?? str
                        ZWTPrint(errorString)
                    }
                    ZWTPrint("request:------")
                    printErrorString(str:myResponse.request?.url?.absoluteString ?? "")
                    if myResponse.request?.httpBody != nil{
                        if let data = myResponse.request?.httpBody{
                            ZWTPrint("body:-----")
                            printErrorString(str: data.utf8String() ?? "")
                        }
                    }
                    ZWTPrint(JSON(myResponse.value ?? [:]))
                }
                #endif
                break
            }
            //****************** debug things *************************///
            if _showError{
                showPrompt(myResponse.message ?? "")
            }
            
            if #available(iOS 9.0, *) {
                let cellularData = CTCellularData()
                if Int(Preference.loadCount ?? "0")!<Config.systemSetting.launchNetworkCount{
                    Preference.loadCount = "\(Int(Preference.loadCount ?? "0")!+1)"
                }
                if Int(Preference.loadCount ?? "0")! > Config.systemSetting.launchNetworkCount{
                    cellularData.cellularDataRestrictionDidUpdateNotifier = {state in
                        if state == .restricted{
                            UIAlertController.alertMessage("请前往 iPhone中的设置>\(Config.App.displayName)>无线数据 并开启网络权限", title: "您的'\(Config.App.displayName)'app访问网络受限", btnTitles: ["我知道了"], action: { (index) in
                                
                            })
                        }
                    }
                }
            } else {
                // Fallback on earlier versions
            }
            
            if code == .outTime{
                NotificationCenter.default.post(name: .userLogout, object: code)
            }
            switch myResponse.result {
            case .success:
                completionHandler(myResponse,code,true);
            case .failure:
                completionHandler(myResponse,code,false);
            }
        }
        return response(
            queue: queue,
            responseSerializer: JSONResponseSerializer(options: options),
            completionHandler: myCompletionHandler
        )
    }
    
    
}
extension Data{
    
    func toResult() -> Result<Any,Error> {
        do {
            let json = try JSONSerialization.jsonObject(with: self, options: .allowFragments)
            return .success(json)
        } catch {
            return .failure(AFError.responseSerializationFailed(reason: .jsonSerializationFailed(error: error)))
        }
    }
}
